﻿using System;
using System.Collections.ObjectModel;
using System.Configuration;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection.Metadata;
using System.Text.Json;
using System.Windows;
using System.Windows.Input;
using System.Xml.Linq;

using Aliphant.Common;
using Aliphant.Common.Helper;
using Aliphant.Datas;
using Aliphant.Interface.Form;
using Aliphant.IoC;
using Aliphant.Mvvm.XEvent.Events;
using Aliphant.Mvvm.XEvent.Events.Base.SubScription;
using Aliphant.Mvvm.XEvent.Interface;
using Aliphant.Mvvm.XEvent.UI;
using Aliphant.UI.Forms.Notify;
using Aliphant.UI.Helper;
using Aliphant.UI.Models;
using Aliphant.UI.Wallpaper.Models;

namespace Aliphant.UI.Wallpaper.ViewModels
{
    public class WallpaperPageViewModel : BindableBase
    {
        private WindowEvent _windowEvent;
        private readonly List<SubScriptionToken> _subscriptionTokens = [];
        private TabPageInfo _tabPageInfo;
        private object _locker = new object();

        public WallpaperPageViewModel()
        {
            _tabPageInfo = new TabPageInfo()
            {
                PageItemCount = 42,
                MaxShowPage = 2
            };

            _windowEvent = WallpaperUIModule.EventAgent.GetEvent<WindowEvent>();
            RegistSubScriptionToken();
            LoadWallpapers();
        }

        #region 绑定属性


        private List<PictureInfo> PictureList = [];

        /// <summary>
        /// 壁纸列表
        /// </summary>
        public ObservableCollection<PictureInfo> PictureCollection { get; private set; } = [];

        public ObservableCollection<PageIndex> ShowPagesCollection { get; private set; } = [];

        private int _currentPageIndex;
        public int CurrentPageIndex
        {
            get => _currentPageIndex;
            set
            {
                if (_currentPageIndex == value) return;
                SetProperty(ref _currentPageIndex, value);
            }
        }

        /// <summary>
        /// 分页控件可用性
        /// </summary>
        private bool _tabBarEnabled = true;
        public bool TabBarEnabled { get => _tabBarEnabled; set => SetProperty(ref _tabBarEnabled, value); }

        /// <summary>
        /// 已选择的图片
        /// </summary>
        private PictureInfo _selectedWallpaper = new PictureInfo();
        public PictureInfo SelectedWallpaper { get => _selectedWallpaper; set => SetProperty(ref _selectedWallpaper, value); }

        private Visibility _loading = Visibility.Collapsed;
        public Visibility Loading { get => _loading; set => SetProperty(ref _loading, value); }

        #endregion


        #region Commands

        public ICommand UploadCommand
        {
            get => new UICommand<object>(obj =>
            {
                Action<string> callback = async path =>
                {
                    if (string.IsNullOrEmpty(path))
                    {
                        return;
                    }
                    var res = await PutPicture(path);
                    if (!res)
                    {
                        NotifyIconHelper.ShowBalloon("上传失败", "Cute Wallpaper", 0, NotifyIconHelper.NotifyLevel.Error);
                        return;
                    }
                    NotifyIconHelper.ShowBalloon("上传成功", "Cute Wallpaper", 0, NotifyIconHelper.NotifyLevel.Info);

                    LoadWallpapers();
                };

                DialogHelper.SelectFileWindow(new WindowEvent
                {
                    Data = "Image Files(*.jpg;*.jpeg;*.png;*.gif;*.bmp;*.tiff;*.ico)|*.jpg;*.jpeg;*.png;*.gif;*.bmp;*.tiff;*.ico",
                    CallBack = callback
                });

            });
        }

        public ICommand RefreshCommand
        {
            get => new UICommand<object>(obj =>
            {
                LoadWallpapers();
            });
        }

        public ICommand LastPageCommand
        {
            get => new UICommand<object>(obj =>
            {
                CurrentPageIndex--;
                if (CurrentPageIndex < 0)
                {
                    CurrentPageIndex = 0;
                    return;
                }

                var page = ShowPagesCollection[_currentPageIndex];
                InitTabPage(page.Mapping);
            });
        }

        public ICommand NextPageCommand
        {
            get => new UICommand<object>(obj =>
            {
                CurrentPageIndex++;
                if (CurrentPageIndex > ShowPagesCollection.Count - 1)
                {
                    CurrentPageIndex = ShowPagesCollection.Count - 1;
                    return;
                }

                var page = ShowPagesCollection[_currentPageIndex];
                InitTabPage(page.Mapping);
            });
        }

        public ICommand SelectedChangeCommand
        {
            get => new UICommand<object>(obj =>
            {
                var page = ShowPagesCollection[CurrentPageIndex];
                InitTabPage(page.Mapping);
            });
        }

        public ICommand SizeUpdatedCommand
        {
            get => new UICommand<double>(contWidth =>
            {
                //Logger.Info($"更新分页控件: 容器宽度: {contWidth}");

            });
        }

        /// <summary>
        /// 设置壁纸
        /// </summary>
        public ICommand SetWallpaperCommand
        {
            get => new UICommand<PictureInfo>(async obj =>
            {
                if (obj is PictureInfo info)
                {
                    await GetOriginPicture(info);

                    var container = IoCServer.Container;
                    var we = container.Resolve<IWallpaper>();
                    we.SetWallpaper(info.Url);
                }
            });
        }

        /// <summary>
        /// 添加播放列表
        /// </summary>
        public ICommand AddtoPlaylistCommand
        {
            get => new UICommand<object>(obj =>
            {

            });
        }

        /// <summary>
        /// 选择壁纸
        /// </summary>
        public ICommand SelectedCommand
        {
            get => new UICommand<PictureInfo>(async obj =>
            {
                if (obj == null) return;

                await GetMiddlePicture(obj);

                SelectedWallpaper.Clear();
                SelectedWallpaper.Middle = obj.Middle;
                SelectedWallpaper.Name = obj.Name;
            });
        }

        /// <summary>
        /// 打开图片查看器
        /// </summary>
        public ICommand ViewPictureCommand
        {
            get => new UICommand<object>(async obj =>
            {
                if (_selectedWallpaper == null) return;

                await GetOriginPicture(_selectedWallpaper);

                _windowEvent.Publish(new WindowEvent
                {
                    Data = _selectedWallpaper.Url,
                    WindowActionType = WindowActionType.Open,
                    EventId = EventIds.OpenViewPictureWindow
                });
            });
        }

        #endregion

        #region Funs

        // 加载壁纸
        private async void LoadWallpapers()
        {
            PictureList.Clear();
            string[] files = await GetPictureListAsync();

            foreach (var file in files)
            {
                PictureList.Add(new PictureInfo(file));
            }
            _tabPageInfo.TotalPage = (int)Math.Ceiling((double)PictureList.Count / _tabPageInfo.PageItemCount);
            InitTabPage();
        }

        private void InitTabPage(int index = 0)
        {
            ShowPagesCollection.Clear();
            if (_tabPageInfo.TotalPage <= _tabPageInfo.MaxShowPage + 2)
            {
                // 显示完整页码
                for (int i = 0; i < _tabPageInfo.TotalPage; i++)
                {
                    var page = new PageIndex()
                    {
                        Show = (i + 1).ToString(),
                        Position = i,
                        Mapping = i,
                    };
                    ShowPagesCollection.Add(page);
                }
                CurrentPageIndex = index;
                FillPictureCollection();
                return;
            }

            UpdateTabPage(index);
        }

        private void UpdateTabPage(int index)
        {
            // 0 1 2 3 4 5 6 7 8
            // -----------------
            // 1 2 3 4 5 6 7 8 9
            // 1 2 ⬛️ 4 5 6 .
            // 1 2 3 ⬛️ 4 5 .
            // . 3 4 ⬛️ 6 7 .
            // . 4 5 ⬛️ 7 8 9
            // . 4 5 6 ⬛️ 8 9
            int current = index;

            ShowPagesCollection.Clear();

            var half = _tabPageInfo.MaxShowPage / 2;

            if (index - half > 1 && index + half < _tabPageInfo.TotalPage - 2)
            {
                // 省略左边和右边

                ShowPagesCollection.Add(new PageIndex
                {
                    Show = "1",
                    Mapping = 0
                });
                ShowPagesCollection.Add(new PageIndex
                {
                    Show = "···",
                    Position = 1,
                    Mapping = index - half - 1
                });

                for (int i = index - half; i < index + half + 1; i++)
                {
                    var page = new PageIndex
                    {
                        Show = (i + 1).ToString(),
                        Mapping = i,
                    };
                    ShowPagesCollection.Add(page);
                    if (i == index)
                    {
                        current = ShowPagesCollection.Count - 1;
                    }
                }

                ShowPagesCollection.Add(new PageIndex
                {
                    Show = "···",
                    Position = 2,
                    Mapping = index + half + 1
                });
                ShowPagesCollection.Add(new PageIndex
                {
                    Show = _tabPageInfo.TotalPage.ToString(),
                    Mapping = _tabPageInfo.TotalPage - 1
                });
            }
            else if (index - half <= 1)
            {
                // 省略右边

                for (int i = 0; i < _tabPageInfo.MaxShowPage + 1; i++)
                {
                    var page = new PageIndex
                    {
                        Show = (i + 1).ToString(),
                        Mapping = i,
                    };
                    ShowPagesCollection.Add(page);
                    if (i == index)
                    {
                        current = ShowPagesCollection.Count - 1;
                    }
                }

                ShowPagesCollection.Add(new PageIndex
                {
                    Show = "···",
                    Position = 2,
                    Mapping = _tabPageInfo.MaxShowPage + 1
                });
                ShowPagesCollection.Add(new PageIndex
                {
                    Show = _tabPageInfo.TotalPage.ToString(),
                    Mapping = _tabPageInfo.TotalPage - 1
                });
            }
            else if (index + half >= _tabPageInfo.TotalPage - 2)
            {
                // 省略左边

                ShowPagesCollection.Add(new PageIndex
                {
                    Show = "1",
                    Mapping = 0
                });

                ShowPagesCollection.Add(new PageIndex
                {
                    Show = "···",
                    Position = 1,
                    Mapping = _tabPageInfo.TotalPage - _tabPageInfo.MaxShowPage - 2
                });
                for (int i = _tabPageInfo.TotalPage - _tabPageInfo.MaxShowPage - 1; i < _tabPageInfo.TotalPage; i++)
                {
                    var page = new PageIndex
                    {
                        Show = (i + 1).ToString(),
                        Mapping = i,
                    };
                    ShowPagesCollection.Add(page);
                    if (i == index)
                    {
                        current = ShowPagesCollection.Count - 1;
                    }
                }
            }

            CurrentPageIndex = current;
            FillPictureCollection();
        }

        private void FillPageList(int index, int half)
        {
            for (int i = index - half; i < index + half; i++)
            {
                var page = new PageIndex
                {
                    Show = (i + 1).ToString(),
                    Position = i,
                    Mapping = i,
                };
                ShowPagesCollection.Add(page);
            }
        }

        private void FillPictureCollection()
        {
            if (ShowPagesCollection.Count == 0)
            {
                return;
            }

            PictureCollection.Clear();
            var page = ShowPagesCollection[CurrentPageIndex];
            var index = page.Mapping;

            var startIndex = _tabPageInfo.PageItemCount * index;
            var endIndex = _tabPageInfo.PageItemCount * (index + 1) - 1;
            if (endIndex > PictureList.Count - 1)
            {
                endIndex = PictureList.Count - 1;
            }

            // 先加载图片列表项
            for (int i = startIndex; i <= endIndex; i++)
            {
                PictureList[i].Clear();
                PictureCollection.Add(PictureList[i]);
            }
            _windowEvent.Publish(new WindowEvent
            {
                EventId = EventIds.UpdateLayout
            });

            // 异步从服务器获取图片并缓存
            if (PictureCollection.Count == 0)
            {
                return;
            }

            string dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "caches", "images");
            if (Directory.Exists(dir))
            {
                Directory.Delete(dir, true);
            }

            string[] urls = PictureCollection.Select(m => m.Name).ToArray();

            int step = 3;   // 加载步进
            int cycTime = (int)Math.Ceiling((double)urls.Length / step);    // 循环次数
            for (int i = 0; i < cycTime; i++)
            {
                int start = i * step;
                int end = i * step + step;
                if (end > urls.Length)
                {
                    end = urls.Length;
                }
                Task.Factory.StartNew(async () =>
                {
                    for (int j = start; j < end; j++)
                    {
                        var res = await GetPreivewPicture(PictureCollection[j]);
                    }
                });
            }

            _windowEvent.Publish(new WindowEvent
            {
                EventId = EventIds.ScrollToTop,
            });
        }


        /// <summary>
        /// 加载画面
        /// </summary>
        /// <param name="isload"></param>
        /// <param name="message">提示内容</param>
        private void OnLoading(bool isload, string? message)
        {
            //Loading.Message = isload ? message ?? "等待中..." : string.Empty;
            //Loading.Visible = isload ? Visibility.Visible : Visibility.Collapsed;
            Loading = isload ? Visibility.Visible : Visibility.Collapsed;
        }

        /// <summary>
        /// 注册通知
        /// </summary>
        private void RegistSubScriptionToken()
        {
            _subscriptionTokens.Add(_windowEvent.Subscribe(DisposeResource, (p) => p.WindowActionType == WindowActionType.Close && p.EventId == EventIds.Release));
            _subscriptionTokens.Add(_windowEvent.Subscribe(ExecuteLoading, (p) => p.WindowActionType == WindowActionType.Close && p.EventId == EventIds.Release));
            _subscriptionTokens.Add(_windowEvent.Subscribe(LoadingComplete, (p) => p.WindowActionType == WindowActionType.Close && p.EventId == EventIds.Release));
        }

        private void UnRegistSubScriptionToken()
        {
            foreach (var item in _subscriptionTokens)
            {
                _windowEvent.UnSubscribe(item);
            }
        }

        /// <summary>
        /// 取消订阅并释放资源
        /// </summary>
        /// <param name="event"></param>
        private void DisposeResource(WindowEvent @event)
        {
            UnRegistSubScriptionToken();
        }

        /// <summary>
        /// 播放等待画面
        /// </summary>
        /// <param name="args"></param>
        private void ExecuteLoading(WindowEvent args)
        {
            OnLoading(true, args.ToString());
        }

        /// <summary>
        /// 播放完成画面
        /// </summary>
        /// <param name="event"></param>
        private void LoadingComplete(WindowEvent @event)
        {
            OnLoading(false, null);
        }

        #endregion

        #region HTTP

        /// <summary>
        /// 获取图片列表
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static async Task<string[]> GetPictureListAsync()
        {
            string? server = ConfigurationManager.AppSettings["server"];
            if (string.IsNullOrEmpty(server))
            {
                return new string[0];
            }

            string url = $"{server}/pictures/list";

            HttpClient client = new HttpClient();
            client.DefaultRequestHeaders.Add("Accept", "application/json");
            try
            {
                var response = await client.GetAsync(url);
                if (response.IsSuccessStatusCode)
                {

                    var content = await response.Content.ReadAsStringAsync();
                    List<string> list = JsonSerializer.Deserialize<List<string>>(content) ?? [];

                    return list.ToArray();

                }
            }
            catch
            {

            }
            return [];
        }

        /// <summary>
        /// 获取压缩图片
        /// </summary>
        /// <param name="image"></param>
        /// <returns></returns>
        public static async Task<bool> GetMiddlePicture(PictureInfo image)
        {
            string path = DomainHelper.GetCachePath("middle." + image.Name, "images");
            if (image.Middle.Equals(path))
            {
                File.SetLastWriteTime(path, DateTime.Now);
                return true;
            }

            path = await GetPicture("middle." + image.Name, image.Name, image.MiddleSize);
            if (string.IsNullOrEmpty(path)) return false;
            image.Middle = path;
            return true;

            //string path = await GetPicture("middle", image.Name, image.MiddleSize);

            //if (string.IsNullOrEmpty(path)) return false;

            //if (!image.Middle.Equals(path))
            //{
            //    image.Middle = path;
            //}
            //return true;
        }

        /// <summary>
        /// 获取预览图
        /// </summary>
        /// <param name="image"></param>
        /// <returns></returns>
        public static async Task<bool> GetPreivewPicture(PictureInfo image)
        {
            string path = DomainHelper.GetCachePath("preview." + image.Name, "images");
            if (image.Preview.Equals(path))
            {
                File.SetLastWriteTime(path, DateTime.Now);
                return true;
            }

            path = await GetPicture("preview." + image.Name, image.Name, image.PreviewSize);
            if (string.IsNullOrEmpty(path)) return false;
            image.Preview = path;
            return true;
        }

        /// <summary>
        /// 下载原图
        /// </summary>
        /// <param name="image"></param>
        /// <returns></returns>
        public static async Task<bool> GetOriginPicture(PictureInfo image)
        {
            string path = await GetPicture("origin", image.Name);

            if (string.IsNullOrEmpty(path)) return false;

            if (!image.Url.Equals(path))
            {
                image.Url = path;
            }
            return true;
        }


        /// <summary>
        /// 下载图片
        /// </summary>
        /// <param name="name">图片名称</param>
        /// <param name="dpi"></param>
        /// <returns></returns>
        public static async Task<string> GetPicture(string fileName, string name, int dpi = -1)
        {
            string? server = ConfigurationManager.AppSettings["server"];
            if (string.IsNullOrEmpty(server))
            {
                return string.Empty;
            }

            string path = DomainHelper.GetCachePath(fileName, "images");
            string url = dpi > 0
                ? $"{server}/pictures/thumbnail/{name}?desiredWidth={dpi}&desiredHeight={dpi}"
                : $"{server}/pictures/{name}";

            try
            {
                using HttpClient client = new HttpClient();
                var response = await client.GetAsync(url);
                if (response.IsSuccessStatusCode)
                {
                    byte[] imageBytes = await response.Content.ReadAsByteArrayAsync();

                    using MemoryStream ms = new MemoryStream(imageBytes);
                    using FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write);

                    ms.CopyTo(fs);
                    return path;
                }


            }
            catch (Exception ex)
            {
                Logger.Error(ex);
            }
            return string.Empty;
        }

        /// <summary>
        /// 上传图片
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static async Task<bool> PutPicture(string filePath)
        {
            string? server = ConfigurationManager.AppSettings["server"];
            if (string.IsNullOrEmpty(server))
            {
                return false;
            }

            string fileName = Path.GetFileName(filePath);
            string url = $"{server}/pictures/upload/{fileName}";

            try
            {
                using HttpClient client = new HttpClient();
                using var content = new MultipartFormDataContent();

                var fileData = await File.ReadAllBytesAsync(filePath);
                var byteContent = new ByteArrayContent(fileData);
                string mimeType = GetMimeType(Path.GetExtension(filePath));
                byteContent.Headers.ContentType = new MediaTypeHeaderValue(mimeType);
                
                content.Add(byteContent, "file", Path.GetFileName(filePath));

                var response = await client.PostAsync(url, content);
                if (response.IsSuccessStatusCode)
                {
                    return true;
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
            }
            return false;
        }

        private static string GetMimeType(string extension)
        {
            return extension switch
            {
                ".txt" => "text/plain",
                ".html" => "text/html",
                ".htm" => "text/html",
                ".css" => "text/css",
                ".csv" => "text/csv",
                ".js" => "application/javascript",
                ".jpg" => "image/jpeg",
                ".jpeg" => "image/jpeg",
                ".png" => "image/png",
                ".gif" => "image/gif",
                ".bmp" => "image/bmp",
                ".svg" => "image/svg+xml",
                ".webp" => "image/webp",
                ".mp3" => "audio/mpeg",
                ".wav" => "audio/wav",
                ".ogg" => "audio/ogg",
                ".mp4" => "video/mp4",
                ".avi" => "video/x-msvideo",
                ".webm" => "video/webm",
                ".mov" => "video/quicktime",
                ".pdf" => "application/pdf",
                ".doc" => "application/msword",
                ".docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                ".xls" => "application/vnd.ms-excel",
                ".xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.document",
                ".ppt" => "application/vnd.ms-powerpoint",
                ".pptx" => "application/vnd.openxmlformats-officedocument.presentationml.presentation",
                ".zip" => "application/zip",
                ".rar" => "application/rar",
                ".7z" => "application/x-7z-compressed",
                ".json" => "application/json",
                _ => "*/*"
            };
        }

        #endregion

        #region Release

        #endregion
    }
}
